//
//  Copyright (C) 2009 Vadim Ushakov
// 
//  This program is free software; you can redistribute it and/or modify it
//  under the terms of the GNU General Public License as published by the Free
//  Software Foundation; either version 2 of the License, or (at your option)
//  any later version.
// 
//  This program is distributed in the hope that it will be useful, but
//  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
//  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
//  for more details.
//  
//  You should have received a copy of the GNU General Public License along
//  with this program; if not, write to the Free Software Foundation, Inc.,
//  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <ailes/graphics.h>
#include <ailes/misc.h>
#include <ailes/window.h>
#include <ailes/multitasker.h>
#include <ailes/rtc.h>
#include <sys/vsh.h>

static int processId = 0;
static int privilege = 0;
static objectKey window = NULL;
static objectKey timerUptimeLabel = NULL;
static objectKey rtcUptimeLabel = NULL;
static objectKey differenceLabel = NULL;
static objectKey deltaLabel = NULL;
static int stop = 0;


static int64_t prevDifference = 0;
static int64_t delta = 0;
static int firstUpdate = 1;

static int getUpdate(void)
{
	int status = 0;
	char labelChar[128];

// Cannot div uint64_t now
#define uint64_t unsigned

	uint64_t mcs = getMicrosecondSoftTimer();
	uint64_t timerUptime = mcs / 1000000;
	uint64_t rtcUptime = rtcUptimeSeconds();

	int64_t difference = timerUptime - rtcUptime;

	if (firstUpdate)
		firstUpdate = 0;
	else
		delta += difference - prevDifference;

	prevDifference = difference;

	sprintf(labelChar, "%u", (unsigned)timerUptime);
	windowComponentSetDataEx(timerUptimeLabel, "text", labelChar, strlen(labelChar));

	sprintf(labelChar, "%u", (unsigned)rtcUptime);
	windowComponentSetDataEx(rtcUptimeLabel, "text", labelChar, strlen(labelChar));

	sprintf(labelChar, "%i", (int)difference);
	windowComponentSetDataEx(differenceLabel, "text", labelChar, strlen(labelChar));

	sprintf(labelChar, "%i", (int)delta);
	windowComponentSetDataEx(deltaLabel, "text", labelChar, strlen(labelChar));

	return (status = 0);
}


static void eventHandler(objectKey key, windowEvent *event)
{
	if ((key == window) && (event->type == EVENT_WINDOW_CLOSE))
	{
		stop = 1;
		windowGuiStop();
		windowDestroy(window);
	}
}


static void constructWindow(void)
{
	componentParameters params;

	window = windowNew(processId, "Clock test");
	if (window == NULL)
		return;

	bzero(&params, sizeof(componentParameters));
	fontGetDefault(&(params.font));
	params.gridWidth = 1;
	params.gridHeight = 1;
	params.padLeft = 5;
	params.padTop = 5;
	params.orientationX = orient_left;
	params.orientationY = orient_top;

	windowNewTextLabel(window, "Uptime (soft timer)", &params);

	params.gridX += 1;
	timerUptimeLabel = windowNewTextLabel(window, "xxxxxxx1", &params);

	params.gridX = 0;
	params.gridY += 1;
	windowNewTextLabel(window, "Uptime (RTC) ", &params);

	params.gridX += 1;
	rtcUptimeLabel = windowNewTextLabel(window, "xxxxxxx2", &params);

	params.gridX = 0;
	params.gridY += 1;
	windowNewTextLabel(window, "Difference ", &params);

	params.gridX += 1;
	differenceLabel = windowNewTextLabel(window, "xxxxxxx3", &params);

	params.gridX = 0;
	params.gridY += 1;
	windowNewTextLabel(window, "Delta ", &params);

	params.gridX += 1;
	deltaLabel = windowNewTextLabel(window, "xxxxxxx4", &params);

	windowRegisterEventHandler(window, &eventHandler);

	windowSetVisible(window, 1);

	return;
}


int main(int argc, char *argv[])
{
	int status = 0;
	int guiThreadPid = 0;


	windowOnlyInGraphicsMode();

	processId = multitaskerGetCurrentProcessId();
	privilege = multitaskerGetProcessPrivilege(processId);

	status = getUpdate();
	if (status < 0)
	{
		if (argc)
			perror(argv[0]);
		return (status);
	}

	constructWindow();

	guiThreadPid = windowGuiThread();

	while (!stop && multitaskerProcessIsAlive(guiThreadPid))
	{
		if (getUpdate() < 0)
			break;
		multitaskerWaitMcs(1000000);
	}

	return (status = 0);
}
